package com.baor.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baor.dao.*;
import com.baor.domain.*;
import com.baor.domain.vx.Amount;
import com.baor.domain.vx.Payer;
import com.baor.service.PayService;
import com.baor.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.text.DateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.baor.utils.DateUtil.now;
import static com.baor.utils.DateUtil.now2;

@Service
public class PayServiceImpl implements PayService {

    @Value("${wechat.appid}")
    private String appid;
    @Value("${wechat.mchid}")
    private String mchid;
    @Value("${wechat.notify_url}")
    private String notify_url;
    @Value("${wechat.serialno}")
    private String serialno;
    @Value("${wechat.key}")
    private String key;
    @Autowired
    private VipDao vipDao;

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private GoodsDao goodsDao;

    @Autowired
    private OrderLogDao orderLogDao;

    @Autowired
    private CarDao carDao;


    @Override
    @Transactional
    public AjaxResult<?> pay(List<CarVo> carVoList) {
        if ( carVoList.size() == 0 )
            return AjaxResult.error("length = 0");
        CarVo carVo = carVoList.get(0);
        if ( carVo.getUserId() == null || "".equals(carVo.getUserId()) )
            return AjaxResult.error("userId is null");

        String userId = carVo.getUserId().toString();
        // 根据用户Id查询用户信息
        UserVo userInfo = vipDao.selectById(userId);
//        OrderVo orderVo = new OrderVo();//???
        long lTime = System.currentTimeMillis();
        // 生成订单
        String coding = "LITTLE" + lTime + userId;

        BigDecimal zero = BigDecimal.ZERO;
        for ( CarVo car : carVoList ){
            GoodsVo goodsVo = goodsDao.selectById(car.getGoodsId());
            BigDecimal multiply = new BigDecimal(car.getNum()).multiply(goodsVo.getPriceValue());
            zero = zero.add(multiply);
            OrderVo orderVo = new OrderVo();
            orderVo.setCreateTime(now());
            orderVo.setOrderCode(coding);
            orderVo.setOrderGoodsNum(Long.valueOf(car.getNum()));
            orderVo.setPriceValue(goodsVo.getPriceValue());
            orderVo.setOrderSubtract(BigDecimal.ZERO);
            orderVo.setOrderDeliveryAmount(BigDecimal.ZERO);
            orderVo.setOrderStatusId("1");
            orderVo.setOrderDeliveryId("1");
            orderVo.setOrderSourceId("1");
            orderVo.setGoodsId(goodsVo.getGoodsId().toString());
            orderVo.setUserId(userId);
            orderVo.setGoodsInvoice("0");
            orderVo.setSiteId(userInfo.getSiteId());
            orderVo.setOrderRealAmount(BigDecimal.ZERO);
            orderDao.insert(orderVo);
            OrderLogVo logVo = new OrderLogVo();
            logVo.setCreateTime(now());
            logVo.setUserName(userInfo.getUserName());
            logVo.setSiteId(userInfo.getSiteId());
            logVo.setOrderId(orderVo.getOrderId().toString());
            logVo.setOrderStatusId("1");
            orderLogDao.insert(logVo);
            logVo.setOrderStatusId("2");
            logVo.setOrderLogId(null);
            orderLogDao.insert(logVo);
            if ( car.getCarId() != null || !"".equals(car.getCarId()) )
                carDao.deleteById(car.getCarId());
        }

        // 组装微信支付参数
        WeChatPayUtil weChatPayUtil = new WeChatPayUtil();
        weChatPayUtil.setAppid(appid);
        weChatPayUtil.setDescription("Image形象店-深圳腾大-QQ公仔");
        weChatPayUtil.setMchid(mchid);
        weChatPayUtil.setNotify_url(notify_url);
        weChatPayUtil.setOut_trade_no(coding);

        Amount amount = new Amount();
        amount.setCurrency("CNY");
//        BigDecimal multiply = new BigDecimal(orderVo.getOrderGoodsNum())
//                .multiply(orderVo.getPriceValue())
//                .multiply(new BigDecimal(100));
//        amount.setTotal(multiply.intValue());
        amount.setTotal(zero.multiply(new BigDecimal(100)).intValue());
        weChatPayUtil.setAmount(amount);

        weChatPayUtil.setPayer(new Payer(userInfo.getWxOpenid()));

        String params = JSON.toJSONString(weChatPayUtil);

        Map<String, Object> data = new HashMap<>();
        data.put("mchid", mchid);
        data.put("serialno", serialno);
        String nonceStr = UUIDHexGenerator.generate();
        long timestamp = lTime / 1000;

        // 打印调试信息
        System.out.println("请求参数: " + params);
        System.out.println("请求数据: " + data);
        System.out.println("生成的签名: " + nonceStr);
        System.out.println("时间戳: " + timestamp);

        // 发起微信支付
        Map<String, Object> res = WeChatPayUtil.httpRequest("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi", "POST", params, data, nonceStr, timestamp);

        // 打印响应
        System.out.println(res.get("response"));

        JSONObject json = (JSONObject) JSONObject.parse((String) res.get("response"));
        json.put("outtradeno", coding);
        json.put("timeStamp",lTime);
        json.put("nonceStr",nonceStr);
        json.put("signType","RSA");
//        String string = res.get("sign").toString();
//        String sign = "error(getSign2 is error) -> call Mr.Nan,thanks";
//        try {
//            sign = AuthorizationHeaderUtil.getSign2(mchid,appid,json.get("prepay_id").toString(),nonceStr,lTime);
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }
//
//        json.put("paySign",sign);
//        System.out.println("this:" + sign);
//        System.out.println("that:" + res.get("sign").toString() );
        return AjaxResult.success(json);
    }

    @Override
    public String receive(Map<String, Object> map) {
        //解密信息
        //支付成功
//        orderDao.updateStatus(map);
//        if (true)
//            return "ok";

        if(!"TRANSACTION.SUCCESS".equals(map.get("event_type").toString()) ){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code","FAIL");
            jsonObject.put("message","失败");
            return jsonObject.toJSONString();
        }
        Map<String,Object> resouce = (Map<String, Object>) map.get("resource");
        AesUtil au = new AesUtil(key.getBytes());
        try {
            /**
             * {id=75873a69-cb90-52a0-9841-8b3d4ecb4a86,
             * create_time=2024-07-03T20:13:54+08:00,
             * resource_type=encrypt-resource,
             * event_type=TRANSACTION.SUCCESS,
             * summary=支付成功,
             * resource={original_type=transaction,
             *              algorithm=AEAD_AES_256_GCM,
             *              ciphertext=xCbPLmYEhvoHWFqvNCoM8VmjGsoaVlL6bSxSBmWRrRgOPLKyBqGgLRLmgiFji6jwTxYrscXq9v7X10HOaTWmNj+aw3ufzH7YB5PlZ2LtFNG2AuaQ7EWSQi56zg8G2aDntJf5ITj5vuHDGXMtYIVk7tu2LiDZCyfhjUv9v63JqqjSNuEl/vt5s1TYijvwysj9YOYOWby9k4iAilYNzmS7z8RBj7MZCqzHKpFpO4atrmvN0cklg32Fiwh4eZgJMCxncAOVRl6lXNjQuLKYqxJw1bQEY7sU0XIZENK7ERuek0aJbh0k5ATU1DdkpcQa/faK7UzL+msuBObNaHEjeMz68KhsYgH4oLjaNDxf9+YNPCPmuo5hpFWoVqtQB4yrG0GlTpJc8aIS7zhQj5FTq7nPtENwu4cYGkVor2JhYyi62W5Odi5PgKWo5FQ1m2NYAqgxdMsyzCgfN88AdvVkXtJ0rv6zI7kFmcaNYSN7lgvXVQlJodWmCah5DWIH7JcpGZ6h3o8Gfz8PIME3Ncn+IgVW7rBVPJpF2KJ8gREZMHLrAOj6avMpip5TDHc2k1vb2VKvgKD5Ag==,
             *              associated_data=transaction,
             *              nonce=MgMUjjYPVmoI}}
             */
            String params = au.decryptToString(resouce.get("associated_data").toString().getBytes("utf-8"),
                    resouce.get("nonce").toString().getBytes(),resouce.get("ciphertext").toString());
            JSONObject res = JSONObject.parseObject(params);
            System.out.println(res);
            Map<String,Object> updateParams = new HashMap<String,Object>();
//            updateParams.put("orderno",res.get("out_trade_no"));
//            updateParams.put("conTime",DateFormat.format());
            updateParams.put("orderCode",res.get("out_trade_no"));
//            updateParams.put("conTime",now());
            int row = orderDao.updateStatus(updateParams);
            List<OrderVo> outTradeNo = orderDao.selectList(new LambdaQueryWrapper<OrderVo>()
                    .eq(OrderVo::getOrderCode, res.get("out_trade_no")));
            for ( OrderVo vo : outTradeNo ){
                BigDecimal priceValue = vo.getPriceValue();
                BigDecimal bigDecimal = new BigDecimal(vo.getOrderGoodsNum());
                BigDecimal subtract = priceValue.multiply(bigDecimal).subtract(vo.getOrderSubtract()).subtract(vo.getOrderDeliveryAmount());
                vo.setOrderRealAmount(subtract);
                orderDao.updateById(vo);
            }
            if(row > 0) {
                //订单信息修改，添加/修改会员信息
                //获取用户信息:
                JSONObject payer = (JSONObject) res.get("payer");
                String openid = (String) payer.get("openid");
                System.out.println("openid:" + openid);
//                UserVo userVo = vipDao.selectOne(new LambdaQueryWrapper<UserVo>()
//                        .eq(UserVo::getWxOpenid, openid));

            }
        } catch ( Exception ex ){
            ex.printStackTrace();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code","FAIL");
            jsonObject.put("message","失败");
            return jsonObject.toJSONString();
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code","SUCCESS");
        jsonObject.put("message","成功");
        return jsonObject.toJSONString();
    }

    @Override
    public AjaxResult<?> two(Integer userId, Integer superiorId) {
        Integer i = vipDao.updateSuperior(userId,superiorId);
        return i > 0 ? AjaxResult.success() : AjaxResult.error();
    }
}